//
//@File    :	7.19_arfupt.cpp
//@Time    :	2021/08/14 17:05:10
//@Auther  :	Sun Sheng
//@Contact :	970340843@qq.com
//@Desc    :	an array of function pointers
//

#include <iostream>

using namespace std;

const double *f1(const double ar[],int n);
const double *f2(const double [],int);
const double *f3(const double *,int);
//以上三个函数返回值和参数列表相同,返回double类型的地址
int main()
{
    double av[3]={1112.3,1542.6,2227.9};

    const double *(*p1)(const double *,int)=f1;
    //声明的同时初始化
    //声明一个指针p1,指向函数f1
    //const double * 为返回了一个double类型的地址
    //(*p1)          为函数名
    //p1             为指向函数的指针
    auto p2=f2;//自动类型推断只能用于单值初始化
    cout<<"Using pointers to functions:\n";
    cout<<" Address Value\n";
    cout<<(*p1)(av,3)<<": "<<*(*p1)(av,3)<<endl;
    cout<<p2(av,3)<<": "<<*p2(av,3)<<endl;


    const double *(*pa[3])(const double *,int)={f1,f2,f3};
    //声明一个指针数组pa[3],pa[0]指向函数f1,pa[1]指向函数f2,pa[2]指向函数f3.
    //声明的同时初始化.运算符[]优先度高于*
    //const double * 为返回了一个double类型的地址
    //(*pa[3])          为函数名

    auto pb=pa;
    //数组名是指向第一个元素的指针
    //pa和pd都是指向函数指针的指针
    //
    //const double *px=pa[0](av,3);
    //const double *py=(*pb[1])(av,3);
    //以上为两种函数调用的方法

    //要获得指向的double指,使用运算符*
    //double x=*pa[0](av,3);
    //double y=*(*pb[1])(av,3);
    cout<<"\nUsing an array of pointers to ffunctions:\n";
    cout<<" Adress Value\n";
    for (int i = 0; i < 3; i++)
    {
        cout<<pa[i](av,3)<<": "<<*pa[i](av,3)<<endl;
    }
    cout<<"\nUsing an array of pointers to ffunctions:\n";
    cout<<" Adress Value\n";
    for (int i = 0; i < 3; i++)
    {
        cout<<pb[i](av,3)<<": "<<*pb[i](av,3)<<endl;
    }
    

    cout<<"\nUsing an array of pointers to ffunctions:\n";
    cout<<" Adress Value\n";
    auto pc=&pa;
    //pc为指向整个指针数组的指针,
    //数组名pa为函数指针的指针
    //所以pc指向指针的指针
    //(*pc)[3] <=> pa[3]
    //pc->pa->函数指针->函数

    //pa与&pa的差别:
    //1.值相同,但类型不同
    //&pa为整个数组的地址,pa为第一个元素的地址
    //&pa+1,指数组后一个跟数组同样大小内存的地址
    //pa+1为数组的第二个元素
    //2.**&pa == *pa ==pa[0]
    cout<<(*pc)[0](av,3)<<": "<<*(*pc)[0](av,3)<<endl;

    const double *(*(*pd)[3])(const double *,int )=&pa;
    //pd 指向数组
    //*pd就是数组
    //(*pd)[i]是数组元素
    //(*pd)[i](av,3)        第一种函数调用方法
    //*(*pd)[i](av,3)       返回的指针指向的值  
    //(*(*pd)[i])(av,3)     第二种函数调用方法
    //*(*(*pd)[i])(av,3)    指向的double值
    const double *pdb=(*pd)[1](av,3);
    cout<<pdb<<": "<<*pdb<<endl;
    cout<<(*(*pd)[2])(av,3)<<": "<<*(*(*pd)[2])(av,3)<<endl;

    system("pause");
    return 0;
}

const double *f1(const double *ar,int n)
{
    return ar;
}
const double *f2(const double ar[],int n)
{
    return ar+1;
}
const double *f3(const double ar[],int n)
{
    return ar+2;
}


//使用typedef进行简化
//typedef const double *(*p_fun)(const double*,int);
//p_fun p1=f1;//p1指向f1函数

//p_fun pa[3]={f1,f2,f3};
//p_fun (*pd)[3]=&pa;